一、 Java 例外繼承體系核心劃分
- Throwable(根節點):所有可被拋出與捕獲的父類別。
- Error(致命錯誤):由硬體或 JVM 資源崩潰引起,應用程式無法也不應捕獲,應觸發告警並重啟。
- Checked Exception(受檢例外):繼承自Exception但非 RuntimeException。編譯期強制要求try-catch或throws宣告,代表可預期的環境客觀問題。
- Unchecked Exception(非受檢例外 / RuntimeException):繼承自RuntimeException。編譯期不強迫捕獲,通常代表程式邏輯缺陷或未滿足前置條件。
二、 現代架構思維:Checked Exception的取捨
- 傳統痛點:Checked Exception 具備傳染性,在介面方法中宣告會將底層實作細節洩漏出去,破壞模組封裝與依賴反轉。
- 現代慣例:業務領域層全面採用RuntimeException。底層基礎設施(如 DB、檔案操作)拋出的Checked Exception,應在DAO/Client架構邊界處進行轉譯(Exception Translation),包裝為自訂的 RuntimeException往上傳遞。
三、 資源防禦:try-with-resources機制
- 使用條件:任何實作java.lang.AutoCloseable(或 Closeable)的物件,均可放入try(...)括號中。
- 自動管理:程式離開該區塊時由JVM保證調用close(),徹底淘汰繁雜且容易出錯的巢狀finally。
- 異常抑制(Suppressed Exceptions):若業務邏輯拋出例外A,同時 close()也拋出例外B,系統會優先拋出主因A,並將B透過 addSuppressed()掛載在A底下,避免真正的主因被遮蔽掩蓋。
四、 企業級自訂業務例外四大原則
- 統一繼承基底:自訂業務例外一律繼承RuntimeException,兼顧乾淨的方法簽名與靈活控制。
- 結構化錯誤碼:搭配ErrorCode列舉(包含內部錯誤碼、展示訊息、HTTP狀態碼),取代零散混亂的字串訊息。
- 保留例外鏈:建構子必須提供傳入Throwable cause的重載版本,確保底層原始異常堆疊不遺失,便於排查問題。
- 全域集中攔截:在最外層(如Controller或全域攔截器)統一捕獲,轉換為標準JSON格式回傳給前端客戶端。